#include "api_include.h"

#define KEY_SUM             		7

/* 按键检测函数 */
uint8_t IsKey1Down(void){return g_hard.key1;}
uint8_t IsKey2Down(void){return g_hard.key2;}
uint8_t IsKey3Down(void){return g_hard.key3;}
uint8_t IsKey4Down(void){return g_hard.key4;}
uint8_t IsKey5Down(void){return g_hard.key5;}
uint8_t IsKey6Down(void){return g_hard.key6;}
uint8_t IsKeyPowerDown(void){return g_hard.power_key;}

/* 按键结构体 */
typedef struct{
    uint8_t     (*IskeyDownFunc)(void);
    uint8_t     KeyState;           /* 按键状态监测 */
    uint8_t     FilterCounter;      /* 滤波器计数器 */
    uint16_t    LongPressCounter;   /* 滤波时间 */
    uint16_t    LongPressTime;      /* 长按保持时间 */
    uint8_t     RepeatSpeed;        /* 连续发送时间 */
    uint8_t     RepeatCounter;      /* 连续发送计数器 */
}Key_T;
Key_T s_TKey[KEY_SUM] = {0};
// = {{IsKey1Down,0},{IsKey2Down,0}};

/* 按键状态FIFO */
#define KEY_FIFO_BUFFER_SIZE    10
typedef volatile struct{
    uint8_t KeyFIFOBuffer[KEY_FIFO_BUFFER_SIZE];
    uint8_t ptrWrite;
    uint8_t ptrRead;
}Key_FIFO_T;
Key_FIFO_T s_TKeyFIFO;

static void KeyFIFOInit(void);
static void KeyValInit(void);
static void KeyDetect(uint8_t _keycnt);

/*
 * @Description:按键FIFO缓冲区初始化
 * @param   {None}
 * @return  {None}
 */
static void KeyFIFOInit(void){
    api_key_clear();
}

/*
 * @Description:从按键FIFO缓冲区读取一个键值
 * @param   {None}
 * @return  {uint8_t}
 */
uint8_t api_key_get(void){
    uint8_t KeyCode = KEY_NONE;

    if(s_TKeyFIFO.ptrRead != s_TKeyFIFO.ptrWrite){
        KeyCode = s_TKeyFIFO.KeyFIFOBuffer[s_TKeyFIFO.ptrRead];
        if(++s_TKeyFIFO.ptrRead >= KEY_FIFO_BUFFER_SIZE)
            s_TKeyFIFO.ptrRead = 0;
    }
    return KeyCode;
}

/*
 * @Description:向按键FIFO缓冲区写入一个键值
 * @param   {uint8_t}_KeyCode
 * @return  {None}
 */
void api_key_put(uint8_t _KeyCode){
    s_TKeyFIFO.KeyFIFOBuffer[s_TKeyFIFO.ptrWrite] = _KeyCode;
    if(++s_TKeyFIFO.ptrWrite >= KEY_FIFO_BUFFER_SIZE)
        s_TKeyFIFO.ptrWrite = 0;
}

void api_key_clear(void){
    s_TKeyFIFO.ptrRead = 0;
    s_TKeyFIFO.ptrWrite = 0;
}

/*
 * @Description:按键相关变量初始化
 * @param   {None}
 * @return  {None}
 */
static void KeyValInit(void){
    uint8_t uci;

    for (uci = 0; uci < KEY_SUM; uci++)
    {
        s_TKey[uci].KeyState = 0;
        s_TKey[uci].FilterCounter = FILTER_TIME;
        s_TKey[uci].LongPressCounter = 0;
        s_TKey[uci].LongPressTime = LONGPRESS_TIME;
        s_TKey[uci].RepeatSpeed = REPEATSPEED;
        s_TKey[uci].RepeatCounter = 0;
    }
    s_TKey[0].IskeyDownFunc = IsKey1Down;
    s_TKey[1].IskeyDownFunc = IsKey2Down;
    s_TKey[2].IskeyDownFunc = IsKey3Down;
    s_TKey[3].IskeyDownFunc = IsKey4Down;
    s_TKey[4].IskeyDownFunc = IsKey5Down;
    s_TKey[5].IskeyDownFunc = IsKey6Down;
	s_TKey[6].IskeyDownFunc = IsKeyPowerDown;
}

/*
 * @Description:按键初始化
 * @param   {None}
 * @return  {None}
 */
void api_key_init(void){
    KeyFIFOInit();
    KeyValInit();
}

/*
 * @Description:按键检测
 * @param   {uint8_t}_keycnt
 * @return  {None}
 */
static void KeyDetect(uint8_t _keycnt){
    
    Key_T *s_key =  &s_TKey[_keycnt];
    
    if (s_key->IskeyDownFunc()){
        if(s_key->FilterCounter < FILTER_TIME){
            s_key->FilterCounter = FILTER_TIME;
        }else if(s_key->FilterCounter < FILTER_TIME*2){
            s_key->FilterCounter++;
        }else{
            /* 按下检测 */
            if (s_key->KeyState == 0){
                s_key->KeyState = 1;
                api_key_put(_keycnt*3+1);
            }
            /* 长按检测 */
            if (s_key->LongPressTime > 0){
                if(s_key->LongPressCounter < s_key->LongPressTime){
                    if(++s_key->LongPressCounter == s_key->LongPressTime){
                        api_key_put(_keycnt*3+3);
                    }
                }else{
                    /* 连续发送判断*/
                    if(s_key->RepeatSpeed > 0){
                        if(++s_key->RepeatCounter == s_key->RepeatSpeed){
                            s_key->RepeatCounter = 0;
                            api_key_put(_keycnt*3+1);
                        }
                    }
                }
            }
        }
    }else{
        if (s_key->FilterCounter > FILTER_TIME){
            s_key->FilterCounter = FILTER_TIME;
        }else if(s_key->FilterCounter != 0){
            s_key->FilterCounter--;
        }else{
            if (s_key->KeyState == 1)
            {
                s_key->KeyState = 0;
                api_key_put(_keycnt*3+2);
            }
        }
        s_key->LongPressCounter = 0;
        s_key->RepeatCounter = 0;
    }
}

/*
 * @Description:按键扫描
 * @param   {None}
 * @return  {None}
 */
void api_key_scan(void){
	static uint8_t ticker = 0;
    uint8_t uci;

	ticker++;
	if(ticker >= 10)
	{
		ticker = 0;
		for(uci=0; uci<KEY_SUM; uci++){
			KeyDetect(uci);
		}
	}
}
